#include "protocol.h"
#include "config.h"




protocol protocol_st;
rx_deal rx_deal_st;


static void read_deal(uint8_t *value, uint16_t len);
static void write_deal(uint8_t *value, uint16_t len);


uint16_t crc_check(uint8_t dir, uint8_t *Rxbuff, uint32_t Rx_len, uint16_t *crc)
{
    uint16_t temp = 0;
    uint32_t len = Rx_len - 2; //
    uint16_t crc_result = 0xffff;
    uint16_t crc_num = 0; //
    int xor_flag = 0;     //
    int i = 0;
    int m = 0;

    if (Rx_len <= 2)
        return HAL_ERROR;
    for (i = 0; i < len; i++) {
        crc_result ^= Rxbuff[i];
        crc_num = (crc_result & 0x0001);
        for (m = 0; m < 8; m++) {
            if (crc_num == 1)
                xor_flag = 1;
            else
                xor_flag = 0;
            crc_result >>= 1;
            if (xor_flag)
                crc_result ^= 0xa001;
            crc_num = (crc_result & 0x0001);
        }
    }
    if (dir == CRC_DIR_RX) {
        temp = (uint16_t) Rxbuff[Rx_len - 1] << 8 | Rxbuff[Rx_len - 2];
        if (crc_result == temp) {
            return HAL_OK;
        } else
            return HAL_ERROR;
    } else if (dir == CRC_DIR_TX) {
        *crc = crc_result;
        return HAL_OK;
    }
}

/****************************************************************************************/
#define PROTOCOL_ADDR     0
void protocol_ini(void) {
    protocol_st.dev_addr = 0x00;
    nvsinternal_read(PROTOCOL_ADDR, &protocol_st.dev_addr, 2);
}


void protocol_flash(uint8_t* data, uint16_t length) {
    uint16_t addr = 0;
    if(sscanf((char*)data, "{Addr:%d}", &addr) == -1) {
        return;
    }
    protocol_ini();
    if(addr != protocol_st.dev_addr) {
        protocol_st.dev_addr = addr;
    }
    nvsinternal_write(PROTOCOL_ADDR, &protocol_st.dev_addr, 2);

}
/****************************************************************************************/

void protocol_rx_deal(uint8_t* data, uint16_t length) {
    //  HAL_UART_Transmit(&huart3, &usart3_rx->RX_pData[0], usart3_rx->RX_Size, 0xFFFF);

    uint8_t *ptr = NULL;
    uint16_t len = 0;
    ptr = &data[0];
    len = length;

    rx_deal_st.head = 0;
    rx_deal_st.addr = 0;
    rx_deal_st.order = 0;
    rx_deal_st.way = 0;
    rx_deal_st.reg_start = 0;
    rx_deal_st.reg_len = 0;
    rx_deal_st.crc = 0;

    if(crc_check(CRC_DIR_RX, ptr, len, &rx_deal_st.crc) != HAL_OK) {
        return;
    }

    rx_deal_st.head = *ptr;
    if((rx_deal_st.head != MASTER_ASK)&&(rx_deal_st.head != MASTER_ACK)) {
        return;
    }

    /**************************************************************/
    rx_deal_st.addr = (*(ptr+1)) << 8;
    rx_deal_st.addr |= (*(ptr+2));
    if(rx_deal_st.addr != protocol_st.dev_addr)
        return;

    rx_deal_st.order = (*(ptr+3));
    if((rx_deal_st.order != ORDER_READ)&&(rx_deal_st.order != ORDER_WRITE)) {
        return;
    }

    rx_deal_st.way = (*(ptr+4));
    if((rx_deal_st.way != WAY_DISCRETE)&&(rx_deal_st.way != WAY_CONTINUOUS)) {
        return;
    }

    if(rx_deal_st.head == MASTER_ASK) {
        rx_deal_st.txbuff[0] = SLAVE_SEND;
        rx_deal_st.txbuff[1] = rx_deal_st.addr >> 8;
        rx_deal_st.txbuff[2] = rx_deal_st.addr;
        rx_deal_st.txbuff[3] = rx_deal_st.order;
        rx_deal_st.txbuff[4] = rx_deal_st.way;

        if(rx_deal_st.order == ORDER_READ) {
            read_deal(ptr,len);
        }else if(rx_deal_st.order == ORDER_WRITE) {
            write_deal(ptr,len);
        }
    }
    if(rx_deal_st.head == MASTER_ACK) {
        if(len > 7)
            return;
        rx_deal_st.ack_value = 0;
        if(rx_deal_st.order == ORDER_READ) {
            if(rx_deal_st.way == WAY_DISCRETE)
                rx_deal_st.ack_value = ACK_READ_DIS;
            else if(rx_deal_st.way == WAY_CONTINUOUS)
                rx_deal_st.ack_value = ACK_READ_CON;
        }
        if(rx_deal_st.order == ORDER_WRITE) {
            if(rx_deal_st.way == WAY_DISCRETE)
                rx_deal_st.ack_value = ACK_WRITE_DIS;
            else if(rx_deal_st.way == WAY_CONTINUOUS)
                rx_deal_st.ack_value = ACK_WRITE_CON;
        }
//        Task_sleep((3000/Clock_tickPeriod));
        easylinkpacksend(&rx_deal_st.ack_value, 1);
    }
}
void read_deal(uint8_t *value, uint16_t len) {
    uint8_t *ptr = NULL;
    ptr = value;
    uint8_t i = 0;
    uint8_t k = 0;

    switch(rx_deal_st.way) {
        case WAY_DISCRETE:
            for(i = 0; i < len - 7; i++) {
                if((*(ptr+5+i)) < REG_NUM) {
                    rx_deal_st.txbuff[5+i*3] = (*(ptr+5+i));
                    rx_deal_st.txbuff[5+i*3+1] = protocol_st.reg_buff[(*(ptr+5+i))] >> 8;
                    rx_deal_st.txbuff[5+i*3+2] = protocol_st.reg_buff[(*(ptr+5+i))];
                }
            }
            crc_check(CRC_DIR_TX, &rx_deal_st.txbuff, (len - 7)*2 + len, &rx_deal_st.crc);
            rx_deal_st.txbuff[(len - 7)*2 + len - 2] = rx_deal_st.crc;
            rx_deal_st.txbuff[(len - 7)*2 + len - 1] = rx_deal_st.crc >> 8;
//            Task_sleep((3000/Clock_tickPeriod));
            easylinkpacksend(&rx_deal_st.txbuff[0], (len - 7)*2 + len);
//            HAL_UART_Transmit(&huart3, &rx_deal_st.txbuff[0], (len - 7)*2 + len, 0xFFFF);
        break;
        case WAY_CONTINUOUS:
            rx_deal_st.reg_start = (*(ptr+5));
            rx_deal_st.reg_len = (*(ptr+6));
            rx_deal_st.txbuff[5] = rx_deal_st.reg_start;
            rx_deal_st.txbuff[6] = rx_deal_st.reg_len;
            if(rx_deal_st.reg_len > REG_NUM ) {
                rx_deal_st.reg_len = REG_NUM;
            }
            for(k = 0; k < rx_deal_st.reg_len; k++) {
                rx_deal_st.txbuff[7+k*2] = protocol_st.reg_buff[rx_deal_st.reg_start+k]>>8;
                rx_deal_st.txbuff[7+k*2+1] = protocol_st.reg_buff[rx_deal_st.reg_start+k];
            }
            crc_check(CRC_DIR_TX, &rx_deal_st.txbuff, rx_deal_st.reg_len*2 + len, &rx_deal_st.crc);
            rx_deal_st.txbuff[rx_deal_st.reg_len*2 + len - 2] = rx_deal_st.crc;
            rx_deal_st.txbuff[rx_deal_st.reg_len*2 + len - 1] = rx_deal_st.crc >> 8;
//            Task_sleep((3000/Clock_tickPeriod));
            easylinkpacksend(&rx_deal_st.txbuff[0], rx_deal_st.reg_len*2 + len);
//            HAL_UART_Transmit(&huart3, &rx_deal_st.txbuff[0], rx_deal_st.reg_len*2 + len, 0xFFFF);
        break;
    }
}
void write_deal(uint8_t *value, uint16_t len) {
    uint8_t *ptr = NULL;
    ptr = value;
    uint8_t i = 0;
    uint8_t k = 0;

    switch(rx_deal_st.way) {
        case WAY_DISCRETE:
            for(i = 0; i < (len - 7) / 3; i++)
            {
                if((*(ptr+5+i*3)) < REG_NUM){
                    protocol_st.reg_buff[(*(ptr+5+i*3))] = (*(ptr+5+i*3+1))<<8;
                    protocol_st.reg_buff[(*(ptr+5+i*3))] |= (*(ptr+5+i*3+2));
                }
                rx_deal_st.txbuff[5+i] = (*(ptr+5+i*3));
            }
            crc_check(CRC_DIR_TX, &rx_deal_st.txbuff,(len - 7)/3 + 7, &rx_deal_st.crc);
            rx_deal_st.txbuff[(len - 7)/3 + 7 - 2] = rx_deal_st.crc;
            rx_deal_st.txbuff[(len - 7)/3 + 7 - 1] = rx_deal_st.crc >> 8;
//            Task_sleep((3000/Clock_tickPeriod));
            easylinkpacksend(&rx_deal_st.txbuff[0], (len - 7)/3 + 7);
//            HAL_UART_Transmit(&huart3, &rx_deal_st.txbuff[0], (len - 7)/3 + 7, 0xFFFF);
        break;
        case WAY_CONTINUOUS:
            rx_deal_st.reg_start = (*(ptr+5));
            rx_deal_st.reg_len = (*(ptr+6));
            rx_deal_st.txbuff[5] = rx_deal_st.reg_start;
            rx_deal_st.txbuff[6] = rx_deal_st.reg_len;
            if(rx_deal_st.reg_len > REG_NUM ) {
                rx_deal_st.reg_len = REG_NUM;
            }
            for(k = 0; k < rx_deal_st.reg_len; k++) {
                protocol_st.reg_buff[rx_deal_st.reg_start+k] = (*(ptr+7+k*2))<<8;
                protocol_st.reg_buff[rx_deal_st.reg_start+k] |= (*(ptr+7+k*2+1));
            }
            crc_check(CRC_DIR_TX, &rx_deal_st.txbuff, 9, &rx_deal_st.crc);
            rx_deal_st.txbuff[9 - 2] = rx_deal_st.crc;
            rx_deal_st.txbuff[9 - 1] = rx_deal_st.crc >> 8;
//            Task_sleep((3000/Clock_tickPeriod));
            easylinkpacksend(&rx_deal_st.txbuff[0], 9);
//            HAL_UART_Transmit(&huart3, &rx_deal_st.txbuff[0], 9, 0xFFFF);
        break;
    }
}
